/*
 This file is part of TEdit
 Copyright (C) 2009 Team16
 Writed by Bonapart(aka Justuser)
All modification should link to me or my page as program creator
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. This program is distributed in the
hope that it will be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License
for more details. You should have received a copy of the GNU General
Public License along with this program. If not, see <http://www.gnu.org/license>
 */
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    selEnc="auto";
setupFileMenu();
 setupEditor();
    fName="";

    this->setContentsMargins(1,1,1,1);
    centralwidget = new QWidget(this);
    centralwidget->setObjectName("");
    gridLayout = new QGridLayout(centralwidget);
    gridLayout->setObjectName("");
    label = new QLabel("TEdit",centralwidget);
    gridLayout->addWidget(label, 0, 0, 1, 1);
    pushButton = new QPushButton("Menu",centralwidget);
    gridLayout->addWidget(pushButton, 0, 1, 1, 1);
    gridLayout->addWidget(editor, 1, 0, 1, 2);
    this->setCentralWidget(centralwidget);
    pushButton->connect(pushButton,SIGNAL(clicked()),this,SLOT(men()));

    dlg=new findDialog(this);
odlg=new options(this);
tdlg=new templates (this);

sip=new QGroupBox(this);
QVBoxLayout *slay=new QVBoxLayout(sip);
QHBoxLayout *ulay=new QHBoxLayout();
QHBoxLayout *mlay=new QHBoxLayout();
QHBoxLayout *llay=new QHBoxLayout();
slay->addLayout(ulay);
slay->addLayout(mlay);
slay->addLayout(llay);

QFont font;
font.fromString("Arial,8.25,-1,5,50,0,0,0,0,0");
font.setFixedPitch(true);
font.setPointSize(14);

sipButtons[34]=new QPushButton("",this);
llay->addWidget(sipButtons[34]);
connect(sipButtons[34],SIGNAL(clicked()),this,SLOT(lngChange()));
sipButtons[34]->setFont(font);

sipButtons[35]=new QPushButton(tr("↓"),this);
mlay->addWidget(sipButtons[35]);
connect(sipButtons[35],SIGNAL(clicked()),this,SLOT(lngUp()));
upped=false;
sipButtons[35]->setFont(font);

for (int i=0;i<34;i++){
    sipButtons[i]=new QPushButton("",this);
    if (i<12){
    ulay->addWidget(sipButtons[i]);
    }else
        if (i>22){
        llay->addWidget(sipButtons[i]);
    }else{
       mlay->addWidget(sipButtons[i]);
    }
    sipButtons[i]->setFont(font);
    connect(sipButtons[i],SIGNAL(clicked()),this,SLOT(sipPush()));
}

sipButtons[36]=new QPushButton("x",this);
llay->addWidget(sipButtons[36]);
connect(sipButtons[36],SIGNAL(clicked()),sip,SLOT(hide()));
sipButtons[36]->setFont(font);


sipButtons[37]=new QPushButton(tr("¬"),this);
mlay->addWidget(sipButtons[37]);
connect(sipButtons[37],SIGNAL(clicked()),this,SLOT(enter()));
sipButtons[37]->setFont(font);

sipButtons[38]=new QPushButton("<-",this);
ulay->addWidget(sipButtons[38]);
connect(sipButtons[38],SIGNAL(clicked()),this,SLOT(backspace()));
sipButtons[38]->setFont(font);

for (int i=0;i<=38;i++){
    sipButtons[i]->setMinimumSize ( 24, 24 );

 sipButtons[i]->setFlat(true);
 sipButtons[i]->setAutoFillBackground(true);
}
sipButtons[34]->setMinimumSize(28,24);

sip->hide();
gridLayout->addWidget(sip,2,0,1,2);

ulay->setSpacing(1);
mlay->setSpacing(1);
llay->setSpacing(1);
slay->setSpacing(1);

slay->setContentsMargins(0,0,0,0);
slay->setContentsMargins(0,0,0,0);

gridLayout->setSpacing(0);
gridLayout->setVerticalSpacing(0);
gridLayout->setContentsMargins(0,0,0,0);


editor->installEventFilter(this);
editor->setAttribute(Qt::WA_InputMethodEnabled,false);

curcod="UTF-8";
label->setMinimumHeight(24);
pushButton->setMinimumHeight(24);

getSet();
if (qApp->argc()>1)
    openFile(qApp->arguments().at(1));


}

void MainWindow::lngUp(){
    upped=!upped;
    if(upped)sipButtons[35]->setText(tr("↑"));else sipButtons[35]->setText(tr("↓"));;
    sipLang();
}

void MainWindow::copy(){
    QClipboard *clipboard = QApplication::clipboard();
    clipboard->setText(editor->textCursor().selectedText());
}

void MainWindow::cut(){
    QClipboard *clipboard = QApplication::clipboard();
    clipboard->setText(editor->textCursor().selectedText());
    editor->insertPlainText("");
}

void MainWindow::paste(){
    QClipboard *clipboard = QApplication::clipboard();
    editor->insertPlainText(clipboard->text());
}

#ifndef Q_OS_SYMBIAN
void MainWindow::expPDF(){
    QString fname=QFileDialog::getSaveFileName(this,tr("PDF file to save"), "e:\\",QString("Pdf (*.pdf)"));

    if (fname.isEmpty())return;
    QPrinter *pr=new QPrinter();
    pr->setOutputFormat(QPrinter::PdfFormat);
    pr->setOutputFileName(fname);
    editor->print(pr);
}

void MainWindow::expHTML(){
    QString fname=QFileDialog::getSaveFileName(this,tr("HTML file to save"),"e:\\","html (*.html)");

    if (fname.isEmpty())return;

            QFile fl(fname);
            if (!fl.open(QIODevice::WriteOnly|QIODevice::Text))return;
        QTextStream out(&fl);
        out.setCodec(QTextCodec::codecForName("UTF-8"));
        out << highlighter->document()->toHtml("utf-8");
        fl.close();
}

#endif

void MainWindow::lngChange(){

    QDir dr("/data/tedit/qwerty/");
    QFileInfoList fp=dr.entryInfoList(QStringList()<<"*.txt");
    sipState=(sipState<fp.count()-1?sipState+1:0);
QFile fl(fp.at(sipState).absoluteFilePath());


if (!fl.open(QFile::ReadOnly|QFile::Text))return;
QTextStream *stream=new QTextStream(&fl);
stream->setCodec(QTextCodec::codecForName("utf-8"));
curent=QString(stream->readAll()).split("\n");

fl.close();

sipButtons[34]->setText(fp.at(sipState).baseName());
    sipLang();
}

bool MainWindow::eventFilter(QObject *obj,QEvent * e){
    if (e->type()==QEvent::RequestSoftwareInputPanel||e->type()==QEvent::MouseButtonDblClick){
sipState=-1;
lngChange();
sip->show();
e->accept();
       return true;
    }
     return QObject::eventFilter(obj, e);
}

void MainWindow::sipShow(){
    sipState=-1;
    lngChange();
    sip->show();
    editor->setFocus();
}

void MainWindow::sipPush(){
   QPushButton *t=(QPushButton *)sender();
   editor->insertPlainText(t->text());
   editor->setFocus();
}

void MainWindow::enter(){
   editor->insertPlainText("\n");
   editor->setFocus();
}

void MainWindow::backspace(){
    editor->textCursor().deletePreviousChar();
    editor->setFocus();
}

void MainWindow::sipLang(){
    for (int i=0;i<3;i++)
        if (upped)
            curent[i]=QString(curent.at(i)).toUpper();
        else
            curent[i]=QString(curent.at(i)).toLower();

        for (int i=0;i<34;i++){
           if (i<12){
           sipButtons[i]->setText(QString(curent.at(0)).at(i));
            }else
                if (i>22){
             sipButtons[i]->setText(QString(curent.at(2)).at(i-23));
            }else{
              sipButtons[i]->setText(QString(curent.at(1)).at(i-12));
            }
            if ( sipButtons[i]->text()=="&") sipButtons[i]->setText("&&");
}}

void MainWindow::changeEvent ( QEvent * event )  {
    QPalette st=qApp->palette();
    st.setColor(QPalette::Normal,QPalette::Base,QColor(255,255,255));
    st.setColor(QPalette::Normal,QPalette::Text,QColor(0,0,0));
    st.setColor(QPalette::Normal,QPalette::Window,QColor(255,255,150));
    st.setColor(QPalette::Normal,QPalette::WindowText,QColor(0,0,0));
    qApp->setPalette(st);
}

void MainWindow::men(){
    fileMenu->exec(pushButton->pos());
}

void MainWindow::newFile()
{
    fName="";
    editor->clear();
}

void MainWindow::openFile(const QString &path)
{
    QString fileName = path;
    if (fName=="")fName="c:/";
    if (fileName.isNull())
        fileName = QFileDialog::getOpenFileName(this,
                                                tr("Open File"), fName, "Text files(*.txt *.ini *.log *.nfo *.text *.info);;Coding files (*.cpp *.h *.py *.js *.vb *.bas *.pas);;Web (*.html *.php *.js *.qs *.phtml *.xhtml);; All files (*.*)");
    if (fName=="c:/")fName="";
    if (!fileName.isEmpty()) {
        QFile file(fileName);

        if (file.open(QFile::ReadOnly | QFile::Text)){
QByteArray txt=file.readAll();
QTextCodec *codec;
            if (selEnc=="auto"){
            int cp=0,koi=0,utf=0;

            if (txt.length()>=3){
                        // bom test
                        if ((unsigned char)txt[0]==239 && (unsigned char)txt[1]==187 && (unsigned char)txt[2]==191) utf=txt.length();
            }

            for (int i=0;i<txt.length();i++){
                        unsigned char u=txt[i];
            if (u==193 ||u==197 ||u==201 ||u==207 ||u==209 || u==213||
                u==225 ||u==129 ||u==233 ||u==239 ||u==241 || u==245)
                koi++;
            if (u==192 ||u==197 ||u==200 ||u==206 ||u==211 ||u==223 ||
                u==124 ||u==129 ||u==232 ||u==238 ||u==243 ||u==255)
                cp++;
            if (i<=txt.length()-1)
            if ((u==208||u==209||u==210) && (unsigned char)txt[i+1]>=128 && (unsigned char)txt[i+1]<=191 )utf++;
if (u>210)utf=-1*txt.length();
                    }
            QString cad="CP1251";
            if (koi>=cp&&koi>=utf)cad="KOI8-R";
            if (utf>=koi&&utf>=cp)cad="UTF-8";
            if (cp>=koi&&cp>=utf)cad="CP1251";

            if (txt.length()>=2){
                // bom test
                if ((unsigned char)txt[0]==254 && (unsigned char)txt[1]==255)cad="UTF-16BE";
            }

            if (txt.length()>=2){
                // bom test
                if ((unsigned char)txt[0]==255 && (unsigned char)txt[1]==254)cad="UTF-16LE";
            }

           codec = QTextCodec::codecForName(cad.toAscii());

            QMessageBox msg;
            msg.setText(tr("Была выбрана кодировка %1").arg(cad));
            msg.exec();
            curcod=cad;
    }else{
        codec = QTextCodec::codecForName(selEnc.toAscii());
            }
        editor->setPlainText(codec->toUnicode(txt));
        highlighter->init(fileName.split(".",QString::SkipEmptyParts).last().trimmed());
        fName=fileName;
        label->setText(fileName);
}}}

void MainWindow::saveFile(){
    QFile fl(fName);
    if (!fl.open(QIODevice::WriteOnly|QIODevice::Text)){
        saveFileAs();
    }else{
        QTextStream out(&fl);
        out.setCodec(QTextCodec::codecForName(curcod.toAscii()));

             out << editor->toPlainText();
        fl.close();
}}

void MainWindow::saveFileAs(){
   QString fileName = QFileDialog::getSaveFileName( this,tr("Save File"), fName, "Text files(*.txt *.ini *.log);;C++ Files (*.cpp *.h);;Web (*.html *.php *.js *.qs *.phtml *.xhtml);; All files (*.*)");
    if (fileName!=""){
       fName=fileName;
       saveFile();
       label->setText(fileName);
       }
}

void MainWindow::setupEditor()
{
    QFont font;
    font.setFamily("Courier");
    font.setFixedPitch(true);
    font.setPointSize(8);
    editor = new QTextEdit;
    editor->setFont(font);
    highlighter = new Highlighter(editor->document());

}

void MainWindow::sizeF(){
    QAction *t=(QAction *)sender();
    QFont font;
    font.setFamily("Courier");
    font.setFixedPitch(true);
    font.setPointSize(t->text().toInt());
    editor->setFont(font);
}

void MainWindow::enc_at(){
    QAction *t=(QAction *)sender();
    if (t->text()!=tr("Авто")){
    selEnc=t->text();
    curcod=selEnc;
}else{
    selEnc="auto";
    curcod="Utf-8";
}}

void MainWindow::high(){
    QAction *t=(QAction *)sender();
    highlighter->init(t->text());
}

void MainWindow::setupFileMenu()
{
    fileMenu = new QMenu(tr("Functions"), this);
    fil = new QMenu(tr("Файл"), this);
    enc = new QMenu(tr("Кодировка"), this);
    hg=new QMenu (tr("Язык подсветки"),this);
    red=new QMenu (tr("Редактирование"),this);

    fileMenu->addAction(tr("-TEdit-"));

    fileMenu->addMenu(fil);
    fil->addAction(tr("Новый"), this, SLOT(newFile()));
    fil->addAction(tr("Открыть"), this, SLOT(openFile()));
    fil->addAction(tr("Сохранить"), this, SLOT(saveFile()));
    fil->addAction(tr("Сохранить как"), this, SLOT(saveFileAs()));

#ifndef Q_OS_SYMBIAN
    QMenu *expm=new QMenu (tr("Экспорт"),this);
    fil->addMenu(expm);
    expm->addAction(tr("PDF"), this,SLOT(expPDF()));
    expm->addAction(tr("HTML"), this,SLOT(expHTML()));
#endif

    fileMenu->addMenu(enc);

    enc->addAction(tr("Авто") , this, SLOT(enc_at()));
    enc->addAction("CP1251" , this, SLOT(enc_at()));
    enc->addAction("UTF-8" , this, SLOT(enc_at()));
    enc->addAction("KOI8-R" , this, SLOT(enc_at()));
    enc->addSeparator();
    for (int i=0;i<QTextCodec::availableCodecs().count();i++)
    enc->addAction(QTextCodec::availableCodecs().at(i), this, SLOT(enc_at()));

    fileMenu->addAction(tr("Настройки"), this, SLOT(opt()));
    fileMenu->addMenu(hg);

    QDir dir("/data/tedit/");
    dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
    dir.setSorting(QDir::Size | QDir::Reversed);

    for (int i=0;i<dir.entryInfoList().count();i++)
        if (dir.entryInfoList().at(i).suffix()=="h")
            hg->addAction(dir.entryInfoList().at(i).baseName() , this, SLOT(high()));

    fileMenu->addMenu(red);
    red->addAction(tr("Поиск ¦ Замена"), this,SLOT(fndr()));
    red->addAction(tr("Искать далее"), this,SLOT(searchNext()));
    red->addSeparator();
    red->addAction(tr("Копировать"), this,SLOT(copy()));
    red->addAction(tr("Вставить"), this,SLOT(paste()));
    red->addAction(tr("Вырезать"), this,SLOT(cut()));
    red->addSeparator();
    red->addAction(tr("В начало"), this,SLOT(toSt()));
    red->addAction(tr("В конец"), this,SLOT(toE()));
    red->addSeparator();
    red->addAction(tr("Виртуальная клава"), this,SLOT(sipShow()));

    fileMenu->addAction(tr("Шаблоны"),this,SLOT(temp()));
    fileMenu->addAction(tr("Выход"), qApp, SLOT(quit()));
}

void MainWindow::temp(){
#ifdef Q_OS_SYMBIAN
tdlg->showFullScreen();
#endif
if (tdlg->exec()==1){
    int h=editor->textCursor().position();
    int u=tdlg->temp.indexOf("|");


    if (u>-1)h+=u;else h+=tdlg->temp.length();
    editor->insertPlainText(tdlg->temp.replace("|",""));
    editor->setFocus();

    QTextCursor o;
    o=editor->textCursor();

    o.setPosition(h);
    editor->setTextCursor(o);
}else{
    editor->setFocus();
}}

void MainWindow::opt(){
#ifdef Q_OS_SYMBIAN
odlg->showFullScreen();
#endif
odlg->exec();
getSet();
}

void MainWindow::getSet(){
    QFont font;
    font.fromString(odlg->efont);
    font.setPointSize(odlg->esize);
    editor->setFont(font);

    QFont mnufont;
    mnufont.fromString(odlg->mfont);
    mnufont.setPointSize(odlg->msize);
    mnufont.setFixedPitch(true);

    fileMenu->setFont(mnufont);
    fil->setFont(mnufont);
    enc->setFont(mnufont);
    hg->setFont(mnufont);
    red->setFont(mnufont);

    QFont font2;
    font2.setPointSize(odlg->ksize);
    for (int i=0;i<39;i++)
        sipButtons[i]->setFont(font2);
}

void MainWindow::fndr(){
    #ifdef Q_OS_SYMBIAN
    dlg->showFullScreen();
    #endif
    int u=dlg->exec();
    if (u>0 && u<5){searchNext();dlg->type=u;}
    if (u>4 && u<9){replaceAll();dlg->type=u-4;}
}

void MainWindow::toSt(){
    editor->moveCursor(QTextCursor::Start,QTextCursor::MoveAnchor);
}

void MainWindow::toE(){
    editor->moveCursor(QTextCursor::End,QTextCursor::MoveAnchor);
}

void MainWindow::searchNext(){
    if (dlg->type==0){
        fndr();
        return;
    }else{
    QTextCursor curs;
    QString fndStr=dlg->searchString;
    QMessageBox trs;
    QString tmp;
    int th;
    int from;
    QRegExp regexp;
        switch(dlg->type){
            case 1://simple
                if (dlg->cs)
                curs=editor->document()->find(fndStr,editor->textCursor(),QTextDocument::FindCaseSensitively);
                else
                    curs=editor->document()->find(fndStr,editor->textCursor());
                break;
            case 2://extended
                fndStr.replace("\\n","\n");
                fndStr.replace("\\r","\r");
                fndStr.replace("\\t","\t");
                tmp=editor->toPlainText();
                from=editor->textCursor().position();
                curs=editor->textCursor();
th=tmp.indexOf(fndStr,from,(dlg->cs)?Qt::CaseSensitive:Qt::CaseInsensitive);
if (th!=-1){
                curs.setPosition(th,QTextCursor::MoveAnchor);
                curs.setPosition(th+fndStr.length(),QTextCursor::KeepAnchor);
            }
                break;
            case 4://regexp
                regexp=QRegExp(fndStr);
                regexp.setCaseSensitivity((dlg->cs)?Qt::CaseSensitive:Qt::CaseInsensitive);
                curs=editor->document()->find(regexp,editor->textCursor());
                break;
            }
if (!curs.isNull() && curs.position()!=from){
       editor->setTextCursor(curs);
       editor->setFocus();
   }else{
       QMessageBox msg;
       msg.setText(tr("В процесе поиска был достигнут конец документа, начать с начала?"));
       msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
       if (msg.exec()==QMessageBox::Yes){
           editor->moveCursor(QTextCursor::Start,QTextCursor::MoveAnchor);
           searchNext();
       }}}
}

void MainWindow::keyPressEvent ( QKeyEvent * event ){
    if (event->key()==Qt::Key_Call)searchNext();
}

void MainWindow::replaceAll(){
    if (dlg->type==0){
        fndr();
        return;
    }else{
        QString fndStr=dlg->searchString;
        QString repStr=dlg->replaceString;
        QRegExp regexp;
        switch(dlg->type){
        case 1://simple
        editor->setPlainText(editor->toPlainText().replace(fndStr,repStr,(dlg->cs)?Qt::CaseSensitive:Qt::CaseInsensitive));
        break;
        case 2://extended
            fndStr.replace("\\n","\n");
            fndStr.replace("\\r","\r");
            fndStr.replace("\\t","\t");
            repStr.replace("\\n","\n");
            repStr.replace("\\r","\r");
            repStr.replace("\\t","\t");
            editor->setPlainText(editor->toPlainText().replace(fndStr,repStr,(dlg->cs)?Qt::CaseSensitive:Qt::CaseInsensitive));
            break;
        case 4://regexp
            regexp=QRegExp(fndStr);
            regexp.setCaseSensitivity((dlg->cs)?Qt::CaseSensitive:Qt::CaseInsensitive);
        editor->setPlainText(editor->toPlainText().replace(regexp,repStr));
        break;
            }}}
